/**
 * Fichier Coordonateur.java : Définition de classe
 * fr.unice.gnpt.gui.utilisateur.Coordonateur : Configuration pour coordonnateur
 * 
 * Auteurs : Groupe GNPT : Gastinel, Nicolas, Pellegrino, Trovato
 */
package fr.unice.gnpt.gui.utilisateur;

import java.util.regex.Pattern;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSeparator;
import javax.swing.JTextField;

import net.miginfocom.layout.CC;
import net.miginfocom.swing.MigLayout;
import fr.unice.gnpt.Main;
import fr.unice.gnpt.core.Cours;
import fr.unice.gnpt.core.Enseignant;
import fr.unice.gnpt.core.Enseignement;
import fr.unice.gnpt.core.Service;
import fr.unice.gnpt.core.ServiceDejaValideException;
import fr.unice.gnpt.core.StatutEnseignant;
import fr.unice.gnpt.core.dao.DaoCours;
import fr.unice.gnpt.core.dao.DaoEnseignant;
import fr.unice.gnpt.core.dao.DaoException;
import fr.unice.gnpt.core.dao.DaoService;
import fr.unice.gnpt.core.dao.connexion.Connexion;
import fr.unice.gnpt.core.dao.connexion.ConnexionException;
import fr.unice.gnpt.gui.Interface;

/**
 * Classe de configuration de l'interface graphique pour un utilisateur de type
 * coordonnateur.
 * <p>
 * Permet de gérer facilement les accès autorisés au coordonnateur.
 * 
 * @author gnpt
 * @version 0.0.1
 */
public class UtilCoordonateur extends Utilisateur {

	// Champs du formulaire de nouvel Enseignant
	private JPanel formulaireEns = null;
	private JTextField formulaireEnsNom;
	private JTextField formulaireEnsPrenom;
	private JComboBox formulaireEnsStatut;
	private JButton formulaireEnsBoutonAjouter;
	// Champs du formulaire de nouveau Cours
	private JPanel formulaireCours = null;
	private JTextField formulaireCoursNom;
	private JTextField formulaireCoursHeuresCM;
	private JTextField formulaireCoursHeuresTD;
	private JTextField formulaireCoursHeuresTP;
	private JTextField formulaireCoursGroupesTD;
	private JTextField formulaireCoursGroupesTP;
	private JButton formulaireCoursBoutonAjouter;
	private JButton buttonValider;

	/**
	 * Constructeur par défaut.
	 * 
	 * @param parent
	 *            l'interface qui contient cet objet.
	 */
	public UtilCoordonateur(Interface parent) {
		super(parent);
	}

	/**
	 * @see fr.unice.gnpt.gui.utilisateur.Utilisateur#creerCadreGauche()
	 */
	@Override
	public void creerCadreGauche() {
		super.creerCadreGauche();

		JPanel gauche = new JPanel(new MigLayout("", "5[grow,fill]5", "[30]"));

		JButton ajouterEnseignant = new JButton("Nouvel enseignant");
		ajouterEnseignant.setActionCommand("ajouterEnseignant");
		ajouterEnseignant.addActionListener(this.getListener());
		JButton ajouterCours = new JButton("Nouveau cours");
		ajouterCours.setActionCommand("ajouterCours");
		ajouterCours.addActionListener(this.getListener());

		gauche.add(ajouterEnseignant, "wrap");
		gauche.add(ajouterCours, "wrap");
		gauche.add(new JSeparator(), "wrap");

		super.getCadreGauche().add(gauche, new CC().dockNorth());
	}

	/**
	 * @see fr.unice.gnpt.gui.utilisateur.Utilisateur#creerInformations()
	 */
	@Override
	public void creerInformations() {

		super.creerInformations();

		this.buttonValider = new JButton(
				"<html><center>Valider<br>le service<br>sélectionné</center></html>");
		this.buttonValider.setActionCommand("gererService");
		this.buttonValider.addActionListener(this.getListener());

		super.getInformations().add(this.buttonValider, new CC().dockEast());
		this.setGestionEnabled(false);
	}

	/**
	 * Formulaire d'ajout d'un enseignant.
	 */
	public void afficheFormulaireNouvelEnseignant() {
		if (this.formulaireEns == null) {

			this.formulaireEns = new JPanel(new MigLayout("",
					"10[grow,fill]10", "10[]"));

			this.formulaireEns.setBorder(BorderFactory
					.createTitledBorder("Nouvel enseignant"));

			// Création des composants
			this.formulaireEnsNom = new JTextField(20);
			this.formulaireEnsNom.setName("ajoutEnsNom");
			this.formulaireEnsNom.addKeyListener(this.getListener());
			this.formulaireEnsPrenom = new JTextField(20);
			this.formulaireEnsPrenom.setName("ajoutEnsPrenom");
			this.formulaireEnsPrenom.addKeyListener(this.getListener());
			this.formulaireEnsStatut = new JComboBox(
					new String[] { "-", "Professeur", "Maître de Conférences",
							"Professeur Agrégé" });
			this.formulaireEnsBoutonAjouter = new JButton("Ajouter");
			this.formulaireEnsBoutonAjouter.addActionListener(this
					.getListener());
			this.formulaireEnsBoutonAjouter
					.setActionCommand("validerAjouterEnseignant");
			this.formulaireEnsBoutonAjouter.setEnabled(false);

			// Ajout
			this.formulaireEns.add(new JLabel("Nom :"));
			this.formulaireEns.add(this.formulaireEnsNom);
			this.formulaireEns.add(new JLabel("Prénom :"));
			this.formulaireEns.add(this.formulaireEnsPrenom);
			this.formulaireEns.add(new JLabel("Statut :"));
			this.formulaireEns.add(this.formulaireEnsStatut);

			this.formulaireEns.add(this.formulaireEnsBoutonAjouter);
		}

		if (this.getFormulaire() != null) {
			this.getContenuEns().remove(this.getFormulaire());
			this.getContenuEns().validate();
		}
		this.setFormulaire(this.formulaireEns);

		this.getContenuEns().add(this.getFormulaire(), new CC().dockNorth());
		this.getContenuEns().validate();
	}

	/**
	 * Formulaire d'ajout d'un cours.
	 */
	public void afficheFormulaireNouveauCours() {
		if (this.formulaireCours == null) {
			this.formulaireCours = new JPanel(new MigLayout("",
					"10[grow,fill]10"));

			this.formulaireCours.setBorder(BorderFactory
					.createTitledBorder("Nouveau cours"));

			// Création des composants
			this.formulaireCoursNom = new JTextField(20);
			this.formulaireCoursNom.setName("ajoutCoursNom");
			this.formulaireCoursNom.addKeyListener(this.getListener());
			this.formulaireCoursHeuresCM = new JTextField(5);
			this.formulaireCoursHeuresCM.setName("ajoutCoursHCM");
			this.formulaireCoursHeuresCM.addKeyListener(this.getListener());
			this.formulaireCoursHeuresTD = new JTextField(5);
			this.formulaireCoursHeuresTD.setName("ajoutCoursHTD");
			this.formulaireCoursHeuresTD.addKeyListener(this.getListener());
			this.formulaireCoursHeuresTP = new JTextField(5);
			this.formulaireCoursHeuresTP.setName("ajoutCoursHTP");
			this.formulaireCoursHeuresTP.addKeyListener(this.getListener());
			this.formulaireCoursGroupesTD = new JTextField(5);
			this.formulaireCoursGroupesTD.setName("ajoutCoursGTD");
			this.formulaireCoursGroupesTD.addKeyListener(this.getListener());
			this.formulaireCoursGroupesTP = new JTextField(5);
			this.formulaireCoursGroupesTP.setName("ajoutCoursGTP");
			this.formulaireCoursGroupesTP.addKeyListener(this.getListener());
			this.formulaireCoursBoutonAjouter = new JButton("Ajouter");
			this.formulaireCoursBoutonAjouter.addActionListener(this
					.getListener());
			this.formulaireCoursBoutonAjouter
					.setActionCommand("validerAjouterCours");
			this.formulaireCoursBoutonAjouter.setEnabled(false);

			// Ajout
			this.formulaireCours.add(new JLabel("Nom :"), "spanY 2");
			this.formulaireCours.add(this.formulaireCoursNom, "spanY 2");
			this.formulaireCours.add(new JLabel("CM :"), "spanY 2");
			this.formulaireCours.add(this.formulaireCoursHeuresCM, "spanY 2");
			this.formulaireCours.add(new JLabel("TD :"), "spanY 2");
			this.formulaireCours.add(this.formulaireCoursHeuresTD);
			this.formulaireCours.add(new JLabel("heure(s)"));
			this.formulaireCours.add(new JLabel("TP :"), "spanY 2");
			this.formulaireCours.add(this.formulaireCoursHeuresTP);
			this.formulaireCours.add(new JLabel("heure(s)"));

			this.formulaireCours.add(this.formulaireCoursBoutonAjouter,
					"spanY 2");

			this.formulaireCours.add(this.formulaireCoursGroupesTD, "cell 5 1");
			this.formulaireCours.add(new JLabel("groupe(s)"), "cell 6 1");
			this.formulaireCours.add(this.formulaireCoursGroupesTP, "cell 8 1");
			this.formulaireCours.add(new JLabel("groupe(s)"), "cell 9 1");
		}

		if (this.getFormulaire() != null) {
			this.getContenuEns().remove(this.getFormulaire());
			this.getContenuEns().validate();
		}
		this.setFormulaire(this.formulaireCours);

		this.getContenuEns().add(this.getFormulaire(), new CC().dockNorth());
		this.getContenuEns().validate();
	}

	/**
	 * Active/désactive le bouton <code>Valider</code>.
	 * 
	 * @see fr.unice.gnpt.gui.utilisateur.Utilisateur#activeGestionEns()
	 */
	@Override
	public void activeGestionEns() {
		boolean b = false;
		int selected = this.getTableEns().getSelectedRow();
		// Aucune ligne sélectionné : -1
		if (selected < 0) { return; }
		selected = this.getTableEns().convertRowIndexToModel(selected);

		if (selected >= 0) {
			Service s = this.getEnsTableModel().getDonneeAt(selected);

			b = (((Enseignement) s).getCours().estPossible(s) && !s.estValide());
		}

		this.setGestionEnabled(b);
	}

	/**
	 * Valide l'enseignement sélectionné.
	 * 
	 * @see fr.unice.gnpt.gui.utilisateur.Utilisateur#gereEns()
	 */
	@Override
	public void gereEns() {
		int selected = this.getTableEns().getSelectedRow();
		selected = this.getTableEns().convertRowIndexToModel(selected);

		if (selected >= 0) {
			Service s = this.getEnsTableModel().getDonneeAt(selected);

			this.valideService(s);
		}
	}

	/**
	 * Active/désactive le bouton <code>Valider</code>.
	 * 
	 * @see fr.unice.gnpt.gui.utilisateur.Utilisateur#activeGestionTAdmin()
	 */
	@Override
	public void activeGestionTAdmin() {
		boolean b = false;
		int selected = this.getTableTAdmin().getSelectedRow();
		// Aucune ligne sélectionné : -1
		if (selected < 0) { return; }
		selected = this.getTableTAdmin().convertRowIndexToModel(selected);

		if (selected >= 0) {
			Service s = this.getTAdminTableModel().getDonneeAt(selected);

			b = !s.estValide();
		}

		this.setGestionEnabled(b);
	}

	/**
	 * Active/désactive le bouton <code>Valider</code>.
	 * 
	 * @see fr.unice.gnpt.gui.utilisateur.Utilisateur#setGestionEnabled(boolean)
	 */
	@Override
	public void setGestionEnabled(boolean b) {
		this.buttonValider.setEnabled(b);
	}

	/**
	 * @see fr.unice.gnpt.gui.utilisateur.Utilisateur#activeGestionDispo()
	 */
	@Override
	public void activeGestionDispo() {
	// TODO Auto-generated method stub

	}

	/**
	 * Valide la tâche administrative sélectionnée.
	 * 
	 * @see fr.unice.gnpt.gui.utilisateur.Utilisateur#gereTAdmin()
	 */
	@Override
	public void gereTAdmin() {
		int selected = this.getTableTAdmin().getSelectedRow();
		selected = this.getTableTAdmin().convertRowIndexToModel(selected);

		if (selected >= 0) {
			Service s = this.getTAdminTableModel().getDonneeAt(selected);

			this.valideService(s);
		}
	}

	/**
	 * @see fr.unice.gnpt.gui.utilisateur.Utilisateur#setGestionDispoEnabled(boolean)
	 */
	@Override
	public void setGestionDispoEnabled(boolean b) {
	// TODO Auto-generated method stub

	}

	/**
	 * @see fr.unice.gnpt.gui.utilisateur.Utilisateur#validerBoutonAjout()
	 */
	@Override
	public void validerBoutonAjout() {
		if (this.getFormulaire() == this.formulaireEns) {
			this.validerBoutonAjoutEns();
		} else if (this.getFormulaire() == this.formulaireCours) {
			this.validerBoutonAjoutCours();
		}
	}

	private void validerBoutonAjoutEns() {
		boolean nom = !this.formulaireEnsNom.getText().isEmpty();
		boolean prenom = !this.formulaireEnsPrenom.getText().isEmpty();

		this.formulaireEnsBoutonAjouter.setEnabled(nom && prenom);
	}

	/**
	 * Ajoute un nouvel enseignant.
	 */
	public void ajouterEnseignant() {
		Enseignant e = new Enseignant(this.formulaireEnsNom.getText(),
				this.formulaireEnsPrenom.getText());
		StatutEnseignant statut = StatutEnseignant.PR;

		switch (this.formulaireEnsStatut.getSelectedIndex()) {
		case 2:
			statut = StatutEnseignant.MC;
			break;
		case 3:
			statut = StatutEnseignant.PRAG;
			break;
		case 0:
		case 1:
		default:
			break;
		}

		e.setStatut(statut);

		this.ajouterEnseignant(e);
	}

	/**
	 * Ajoute un enseignant à la base de données.
	 * 
	 * @param nouvelEnseignant
	 *            le nouvel enseignant à insérer dans la base de données.
	 */
	protected void ajouterEnseignant(Enseignant nouvelEnseignant) {
		DaoEnseignant daoEnseignant = this.getFabrique().getDaoEnseignant();
		Connexion<?> connexion = daoEnseignant.getConnexion();

		try {
			connexion.ouvrir();
			connexion.beginTransaction();
			daoEnseignant.create(nouvelEnseignant);
			connexion.commitTransaction();

			this.reInititaliseFormulaire();
			this.setListeEnseignants();
			this.rafraichir();
			this.getFrame().setStatus("Enseignant ajouté");
		} catch (DaoException e) {
			Main.getJournal().logException(e,
					"Echec de l'ajout d'un enseignant", true, true);
			if (connexion.transactionEnCours())
				try {
					connexion.rollbackTransaction();
				} catch (ConnexionException e1) {
					Main.getJournal().logException(e, "Erreur de connexion",
							false, true);
				}
			this.getFrame().setStatus("Echec de l'ajout de l'enseignant");
		} finally {
			try {
				connexion.fermer();
			} catch (ConnexionException e) {
				Main.getJournal().logException(e,
						"Echec lors de la fermeture de la connexion");
			}
		}
	}

	private void validerBoutonAjoutCours() {
		String estEntierPositif = "0*[1-9]\\d*";

		boolean nom = !this.formulaireCoursNom.getText().isEmpty();
		boolean isIntHCM = Pattern.matches(estEntierPositif,
				this.formulaireCoursHeuresCM.getText())
				|| this.formulaireCoursHeuresCM.getText().isEmpty();
		boolean isIntTD = (Pattern.matches(estEntierPositif,
				this.formulaireCoursHeuresTD.getText()) && Pattern.matches(
				estEntierPositif, this.formulaireCoursGroupesTD.getText()))
				|| (this.formulaireCoursHeuresTD.getText().isEmpty() && this.formulaireCoursHeuresTD
						.getText().isEmpty());
		boolean isIntTP = (Pattern.matches(estEntierPositif,
				this.formulaireCoursHeuresTP.getText()) && Pattern.matches(
				estEntierPositif, this.formulaireCoursGroupesTP.getText()))
				|| (this.formulaireCoursHeuresTP.getText().isEmpty() && this.formulaireCoursGroupesTP
						.getText().isEmpty());

		this.formulaireCoursBoutonAjouter.setEnabled(nom && isIntHCM && isIntTD
				&& isIntTP);
	}

	/**
	 * Ajoute un nouveau cours.
	 */
	public void ajouterCours() {
		// Nom du cours
		String nom = this.formulaireCoursNom.getText();
		// Cours magistral
		int hCM = 0;
		if (!this.formulaireCoursHeuresCM.getText().isEmpty()) {
			try {
				hCM = Integer.parseInt(this.formulaireCoursHeuresCM.getText());
			} catch (NumberFormatException e) {
				hCM = 0;
			}
		}
		// Travaux dirigés
		int hTD = 0, gTD = 0;
		if (!this.formulaireCoursHeuresTD.getText().isEmpty()) {
			try {
				hTD = Integer.parseInt(this.formulaireCoursHeuresTD.getText());
			} catch (NumberFormatException e) {
				hTD = 0;
			}
			try {
				gTD = Integer.parseInt(this.formulaireCoursGroupesTD.getText());
			} catch (NumberFormatException e) {
				gTD = 0;
			}
		}
		// Travaux pratiques
		int hTP = 0, gTP = 0;
		if (!this.formulaireCoursHeuresTP.getText().isEmpty()) {
			try {
				hTP = Integer.parseInt(this.formulaireCoursHeuresTP.getText());
			} catch (NumberFormatException e) {
				hTP = 0;
			}
			try {
				gTP = Integer.parseInt(this.formulaireCoursGroupesTP.getText());
			} catch (NumberFormatException e) {
				gTP = 0;
			}
		}

		Cours nouveauCours = new Cours(nom, hCM, hTD, gTD, hTP, gTP);
		this.ajouterCours(nouveauCours);
	}

	/**
	 * Ajoute un cours à la base de données.
	 * 
	 * @param nouveauCours
	 *            le nouveau cours a insérer dans la base de données.
	 */
	protected void ajouterCours(Cours nouveauCours) {
		DaoCours daoCours = this.getFabrique().getDaoCours();
		Connexion<?> connexion = daoCours.getConnexion();

		try {
			connexion.ouvrir();
			connexion.beginTransaction();
			daoCours.create(nouveauCours);
			connexion.commitTransaction();

			this.reInititaliseFormulaire();
			this.setListeEnseignants();
			this.rafraichir();
			this.getFrame().setStatus("Cours ajouté");
		} catch (DaoException e) {
			Main.getJournal().logException(e, "Echec de l'ajout d'un cours",
					true, true);
			try {
				connexion.rollbackTransaction();
			} catch (ConnexionException e1) {
				Main.getJournal().logException(e, "Erreur de connexion", false,
						true);
				this.getFrame().setStatus("Echec de l'ajout du cours");
			}
		} finally {
			try {
				connexion.fermer();
			} catch (ConnexionException e) {
				Main.getJournal().logException(e,
						"Echec lors de la fermeture de la connexion");
			}
		}
	}

	/**
	 * Valide un service et l'enregistre dans la base.
	 * 
	 * @param s
	 */
	private void valideService(Service s) {
		this.setGestionEnabled(false);
		DaoService daoServ = this.getFabrique().getDaoService();
		Connexion<?> connexion = daoServ.getConnexion();

		try {
			connexion.ouvrir();
			connexion.beginTransaction();

			if (s instanceof Enseignement) {
				Cours c = ((Enseignement) s).getCours();
				for (Enseignement e : c.getConflits((Enseignement) s)) {
					c.supprimerEnseignement(e);
					daoServ.delete(e);

					DaoCours daoc = this.getFabrique().getDaoCours();
					daoc.getConnexion().ouvrir();
					daoc.getConnexion().beginTransaction();
					daoc.update(c);
					daoc.getConnexion().commitTransaction();
					daoc.getConnexion().fermer();
				}
			}

			s.valider();
			daoServ.update(s);

			connexion.commitTransaction();
		} catch (DaoException e) {
			Main.getJournal().logException(e);
			if (connexion.transactionEnCours())
				try {
					connexion.rollbackTransaction();
				} catch (ConnexionException e1) {
					Main.getJournal().logException(e, "Erreur de connexion",
							false, true);
				}
		} catch (ServiceDejaValideException e) {
			Main.getJournal().logException(e, "Service validé :" + s);
		} finally {
			try {
				connexion.fermer();
			} catch (ConnexionException e) {
				Main.getJournal().logException(e,
						"Echec lors de la fermeture de la connexion");
			}
		}

		this.rafraichir();
	}

	/**
	 * @see fr.unice.gnpt.gui.utilisateur.Utilisateur#reInititaliseFormulaire()
	 */
	@Override
	public void reInititaliseFormulaire() {
		if (this.getFrame().getTabs().getSelectedIndex() == 0) {
			if (this.formulaireCours != null) {
				this.formulaireCoursNom.setText("");
				this.formulaireCoursHeuresCM.setText("");
				this.formulaireCoursHeuresTD.setText("");
				this.formulaireCoursHeuresTP.setText("");
				this.formulaireCoursGroupesTD.setText("");
				this.formulaireCoursGroupesTP.setText("");
			}
			if (this.formulaireEns != null) {
				this.formulaireEnsNom.setText("");
				this.formulaireEnsPrenom.setText("");
				this.formulaireEnsStatut.setSelectedIndex(0);
			}
		}
	}

	/**
	 * @see java.lang.Object#toString()
	 */
	@Override
	public String toString() {
		return "coordonnateur";
	}
}
